import zmq
from derbyos import DerbyXML
from derbyos import Stopwatch
from derbyos import NSOde
from derbyos import BoutStates
import wx
import wxDerbyOS
from wxDerbyOS import UpdateOnMainThread, Stopwatcher, UpdateLabelOnMainThread
import logging


class NSOdeScoreboardLayout(object):
    def formatStaticLabel(self, label):
        label.SetFont(wx.Font(20, wx.DEFAULT, wx.NORMAL, wx.BOLD))
        label.SetBackgroundColour(wx.NullColour)
        label.SetForegroundColour(wx.Colour(255, 255, 255, 255))
        label.SetWindowStyle(wx.ALIGN_CENTRE)
        label.Layout()

    def formatDynamicLabel(self, label, highlight=False):
        label.SetFont(wx.Font(20, wx.DEFAULT, wx.NORMAL, wx.BOLD))
        label.SetWindowStyle(wx.ALIGN_CENTRE)
        if highlight:
            label.SetBackgroundColour(wx.Colour(255, 0, 0, 255))
        else:
            label.SetBackgroundColour(wx.Colour(255, 255, 255, 255))
        label.SetForegroundColour(wx.Colour(0, 0, 0, 255))
        label.Layout()

    def layoutScoreboard(self, sb):
        sb.SetBackgroundColour(wx.Colour(0, 0, 0, 255))
        self.hsplit1 = wx.FlexGridSizer(wx.VERTICAL, 1, 2)  #, rows=2, cols = 1)
        self.teamSplit = wx.FlexGridSizer(wx.HORIZONTAL, 3, 1)  #, rows=1, cols=3)
        self.homeSplit = wx.FlexGridSizer(wx.VERTICAL, 1, 3)  #, rows=3, cols=1)
        self.awaySplit = wx.FlexGridSizer(wx.VERTICAL, 1, 3)  #, rows=3, cols=1)
        self.timeoutSplit = wx.FlexGridSizer(wx.VERTICAL, 1, 3)  #, rows=3, cols=1)
        self.timerSplit = wx.FlexGridSizer(wx.HORIZONTAL, 2, 2)
        self.timeoutSplitTeams = wx.FlexGridSizer(wx.HORIZONTAL, 3, 1)

        self.hsplit1.Add(self.teamSplit, 0, wx.EXPAND)
        self.hsplit1.Add(self.timerSplit, 1, wx.EXPAND)
        self.teamSplit.Add(self.homeSplit, 0, wx.EXPAND)
        self.teamSplit.Add(self.timeoutSplit, 1, wx.EXPAND)
        self.teamSplit.Add(self.awaySplit, 2, wx.EXPAND)

        self.awaySplit.Add(sb.awayLabel, 0, wx.EXPAND)
        self.awaySplit.Add(sb.awayScore, 1, wx.EXPAND)
        self.homeSplit.Add(sb.homeLabel, 0, wx.EXPAND)
        self.homeSplit.Add(sb.homeScore, 1, wx.EXPAND)

        self.timeoutSplit.Add(sb.timeoutLabel, 0, wx.EXPAND)
        self.timeoutSplit.Add(self.timeoutSplitTeams, 1, wx.EXPAND)
        self.timeoutSplitTeams.Add(sb.homeTimeouts, 0, wx.EXPAND)
        self.timeoutSplitTeams.AddStretchSpacer()
        self.timeoutSplitTeams.Add(sb.awayTimeouts, 1, wx.EXPAND)

        self.timerSplit.Add(sb.periodLabel, 0, wx.EXPAND)
        self.timerSplit.Add(sb.jamLabel, 1, wx.EXPAND)

        self.timerSplit.Add(sb.periodTime, 0, wx.EXPAND)
        self.timerSplit.Add(sb.jamTime, 1, wx.EXPAND)
        self.timerSplit.Add(sb.lineupTime, 2, wx.EXPAND)
        self.timerSplit.Add(sb.timeoutTime, 3, wx.EXPAND)

        sb.SetSizer(self.hsplit1)
        sb.SetAutoLayout(1)
        self.hsplit1.Fit(sb)


class NSOdeScoreboard(wx.Frame):
    def __init__(self, nsode):
        self.nsode = nsode
        super(NSOdeScoreboard, self).__init__(None, title="Scoreboard",
                                              size=(400, -1))
        self.layout = NSOdeScoreboardLayout()

        self.homeLabel = wx.StaticText(self, label="Home")
        self.layout.formatStaticLabel(self.homeLabel)
        self.homeScore = wx.StaticText(self, label="0")
        self.layout.formatDynamicLabel(self.homeScore)

        self.awayLabel = wx.StaticText(self, label="Away")
        self.layout.formatStaticLabel(self.awayLabel)
        self.awayScore = wx.StaticText(self, label="0")
        self.layout.formatDynamicLabel(self.awayScore)

        self.timeoutLabel = wx.StaticText(self, label="Timeouts")
        self.layout.formatStaticLabel(self.timeoutLabel)
        self.homeTimeouts = wx.StaticText(self, label="3")
        self.layout.formatDynamicLabel(self.homeTimeouts)
        self.awayTimeouts = wx.StaticText(self, label="3")
        self.layout.formatDynamicLabel(self.awayTimeouts)

        self.periodLabel = wx.StaticText(self, label="Period 1")
        self.layout.formatDynamicLabel(self.periodLabel)
        self.jamLabel = wx.StaticText(self, label="Jam 1")
        self.layout.formatDynamicLabel(self.jamLabel)
        self.periodTime = wx.StaticText(self, label="30:00")
        self.layout.formatDynamicLabel(self.periodTime)
        self.jamTime = wx.StaticText(self, label="2:00")
        self.layout.formatDynamicLabel(self.jamTime)
        self.lineupTime = wx.StaticText(self, label="0:00")
        self.layout.formatDynamicLabel(self.lineupTime)
        self.timeoutTime = wx.StaticText(self, label="0:00")
        self.layout.formatDynamicLabel(self.timeoutTime)

        #        self.sizer.Add(self.control, 1, wx.EXPAND)

        self.layout.layoutScoreboard(self)

        def StateChanged(obj, name, value):
            print "State", value

        self.nsode.boutState.addObserver(StateChanged, "boutState")

    def OnStart(self, event):
        self.nsode.StartJam()

    def OnStop(self, event):
        pass

    def OnTimeOut(self, event):
        pass


class NSOdeScoreboardViaTimers(NSOdeScoreboard):
    def __init__(self, nsode):
        self.nsode = nsode
        super(NSOdeScoreboardViaTimers, self).__init__(nsode)
        # setup notification
        def UpdateJam(xml, attr, value):
            print "Updating jam"
            self.jamTime.SetLabelText(str(value))

        self.nsode.addObserver(UpdateOnMainThread(self, UpdateJam), "DerbyXML:timer[@id='jam']")

        def UpdatePeriod(xml, attr, value):
            print "Updating period"
            self.periodTime.SetLabelText(str(value))

        self.nsode.addObserver(UpdateOnMainThread(self, UpdatePeriod), "DerbyXML:timer[@id='period']")


class NSOdeScoreboardViaEvents(NSOdeScoreboard):
    def __init__(self, nsode):
        self.nsode = nsode
        super(NSOdeScoreboardViaEvents, self).__init__(nsode)
        # we have our own timers
        self.jamTimer = Stopwatch(0.2, 120, False)
        self.periodTimer = Stopwatch(0.2, 30 * 60, False)
        self.lineupTimer = Stopwatch(0.2, 30)
        self.timeoutTimer = Stopwatch(0.2, 60 * 60)
        self.intermissionTimer = Stopwatch(0.2, 12 * 60 * 60)
        self.oldBoutState = BoutStates.PENDING

        def StateChanged(obj, name, value):
            #print "@@@State",value
            if value == self.oldBoutState:
                return
            if BoutStates.ShouldPeriodClockRun(value):
                if self.oldBoutState in [BoutStates.PENDING, BoutStates.INTERMISSION]:
                    print "> Starting period timer"
                    self.periodTimer.StartTimer()
                else:
                    print "> Resuming period timer"
                    self.periodTimer.ResumeTimer()
            else:
                print "> Stopping period timer"
                self.periodTimer.StopTimer()
            if BoutStates.ShouldJamClockRun(value) and not BoutStates.ShouldJamClockRun(self.oldBoutState):
                print "> Starting jam timer"
                self.jamTimer.StartTimer()
            else:
                print "> Stopping jam timer"
                self.jamTimer.StopTimer()
            if BoutStates.ShouldLineupClockRun(value) and not BoutStates.ShouldLineupClockRun(self.oldBoutState):
                print "> Starting lineup timer"
                self.lineupTimer.StartTimer()
            else:
                print "> Stoppping lineup timer"
                self.lineupTimer.StopTimer()
            if BoutStates.ShouldTimeoutClockRun(value) and not BoutStates.ShouldTimeoutClockRun(self.oldBoutState):
                print "> Starting timeout timer"
                self.timeoutTimer.StartTimer()
            else:
                print "> Stopping timeout timer"
                self.timeoutTimer.StopTimer()
            if BoutStates.ShouldIntermissionClockRun(value) and not BoutStates.ShouldIntermissionClockRun(
                    self.oldBoutState):
                print "> Starting intermission timer"
                self.intermissionTimer.StartTimer()
            else:
                print "> Stopping intermission timer"
                self.intermissionTimer.StopTimer()
            self.oldBoutState = value


        self.nsode.boutState.addObserver(UpdateOnMainThread(self, StateChanged), "boutState")
        self.nsode.boutState.addObserver(UpdateLabelOnMainThread(self, self.periodLabel, lambda x: "Period " + str(x)),
                                         "periodNumber")
        self.nsode.boutState.addObserver(UpdateLabelOnMainThread(self, self.jamLabel, lambda x: "Jam " + str(x)),
                                         "jamNumber")
        self.nsode.boutState.addObserver(UpdateLabelOnMainThread(self, self.homeScore), "homeScore")
        self.nsode.boutState.addObserver(UpdateLabelOnMainThread(self, self.awayScore), "awayScore")
        # install watchers on the timers, so we can updaate the UI
        mainUpdate = UpdateOnMainThread(self, self.UpdateTimer)
        self.watchers = [Stopwatcher(self.jamTimer, "jam", self.nsode, mainUpdate),
                         Stopwatcher(self.periodTimer, "period", self.nsode, mainUpdate),
                         Stopwatcher(self.lineupTimer, "lineup", self.nsode, mainUpdate),
                         Stopwatcher(self.timeoutTimer, "timeout", self.nsode, mainUpdate),
                         Stopwatcher(self.intermissionTimer, "intermission", self.nsode, mainUpdate)]

    def UpdateTimer(self, timer):
        if timer == self.jamTimer:
            self.jamTime.SetLabelText(timer.FormattedTime())
        elif timer == self.periodTimer:
            self.periodTime.SetLabelText(timer.FormattedTime())
        elif timer == self.lineupTimer:
            self.lineupTime.SetLabelText(timer.FormattedTime())
        elif timer == self.timeoutTimer:
            self.timeoutTime.SetLabelText(timer.FormattedTime())
        elif timer == self.intermissionTimer:
            #self.UpdateIntermissionTimer()
            pass


if __name__ == '__main__':
    wxDerbyOS.testWX("Scoreboard", NSOdeScoreboardViaEvents)
